/*
 * SDL视频系统
 * 
 * 最后修改: 2006年12月1日星期五
 * 文曦畅
 *
 * 历史:
 */

#include <SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL_image.h>
#include <SDL_rotozoom.h>

#include "base.h"

#define _R_X	800
#define _R_Y	600
#define _BPP	4

SDL_Surface *screen;
static SDL_Surface *display_scr;

Uint32 fore_color = 0xffffff;
Uint32 bk_color = 0;		//记录背景颜色

int draw_lock = 1;		//绘图锁,只有0时才允许绘图

void video_reset_screen()
{
	screen = display_scr;
}

void video_set_screen(Image img)
{
	screen = img;
}

void video_start_draw()
{
	if (SDL_MUSTLOCK(screen))
		if (SDL_LockSurface(screen) < 0)
			draw_lock = 1;
	draw_lock = 0;
}

void video_end_draw()
{
	if (SDL_MUSTLOCK(screen))
		SDL_UnlockSurface(screen);
	
	SDL_Flip(screen);
	draw_lock = 1;
}

int video_init()
{
	if(SDL_Init(SDL_INIT_VIDEO) < 0) {
		fprintf(stderr, "Error init SDL: %s, exit.\n",
			SDL_GetError());
		exit(-1);
	}
	atexit(SDL_Quit);

	display_scr = SDL_SetVideoMode(_R_X, _R_Y, _BPP * 8,
				  SDL_HWSURFACE | SDL_DOUBLEBUF);
	if(display_scr == NULL) {
		display_scr = SDL_SetVideoMode(_R_X, _R_Y, _BPP * 8,
					  SDL_SWSURFACE);
		fprintf(stderr, "Error init video：%s, exit.\n",
			SDL_GetError());
		exit(-1);
	}
	video_reset_screen();
	return 0;
}

Image video_create_image(int width, int height)
{
	Image surface, ret;
	Uint32 rmask, gmask, bmask, amask;
	
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
	rmask = 0xff000000;
	gmask = 0x00ff0000;
	bmask = 0x0000ff00;
	amask = 0x000000ff;
#else
	rmask = 0x000000ff;
	gmask = 0x0000ff00;
	bmask = 0x00ff0000;
	amask = 0xff000000;
#endif

	surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,
					rmask, gmask, bmask, amask);
	if(surface == NULL) {
		fprintf(stderr, "create image failed: %s\n", SDL_GetError());
		exit(1);
	}
	SDL_SetColorKey(surface, SDL_SRCCOLORKEY, 0);
	ret = SDL_DisplayFormat(surface);
	SDL_FreeSurface(surface);
	return ret;
}

void video_set_caption(char *cap)
{
	SDL_WM_SetCaption(cap, NULL);	//设置窗口标题
}

void video_clear()
{
	if(draw_lock) return;
	static SDL_Rect scds = {0, 0, 0, 0};
	scds.w = screen -> w;
	scds.h = screen -> h;
	//if(bk_color == 0)
	//	memset(screen -> pixels, 0, _R_X * _R_Y * _BPP);
	SDL_FillRect(screen, &scds, bk_color);
}

void video_set_bkcolor(Uint8 R, Uint8 G, Uint8 B)
{
	bk_color = SDL_MapRGB(screen -> format, R, G, B);
}

void video_set_color(Uint8 R, Uint8 G, Uint8 B)
{
	fore_color = SDL_MapRGB(screen -> format, R, G, B);
}

void video_put_pixel(int x, int y)
{
	if(draw_lock) return;
	if(x >= screen -> w) return;
	if(y >= screen -> h) return;
	if(x < 0 || y < 0) return;

	switch (_BPP) {
		case 1: { /* 假定是8-bpp */
			Uint8 *bufp;

			bufp = (Uint8 *)screen -> pixels + 
					y * screen -> pitch + x;
			*bufp = fore_color;
		}
		break;
		case 2: { /* 可能是15-bpp 或者 16-bpp */
			Uint16 *bufp;

			bufp = (Uint16 *)screen -> pixels + 
					y * screen -> pitch / 2 + x;
			*bufp = fore_color;
		}
		break;
		case 3: { /* 慢速的24-bpp模式，通常不用 */
			fprintf(stderr, 
				"24-bpp mode not supported.\n");
		}
		break;
		case 4: { /* 可能是32-bpp */
			Uint32 *bufp;

			bufp = (Uint32 *)screen -> pixels + 
					y * screen -> pitch / 4 + x;
			*bufp = fore_color;
		}
		break;
		default:
			fprintf(stderr, "Put pixels failed\n");
	}
}


void video_line(int x1, int y1, int x2, int y2)
{
	int x, y, dx, dy,
	mid, et, i, flag;

	dx = x2 - x1;
	dy = y2 - y1;

	if(abs(dy) < abs(dx)) {
		if (dx < 0) {
			i = x1; x1 = x2; x2 = i;
			i = y1; y1 = y2; y2 = i;
			dx = x2 - x1;
			dy = y2 - y1;
		}

		if (dy < 0) flag = -1;
		else flag = 1;

		dy = abs(dy);
		mid = dx >> 1;
		et = 0;
		x = x1;
		y = y1;

		for (i = 0; i < dx; i++) {
			video_put_pixel(x, y);
			x++;
			et += dy;
			if (et > mid) {
				et -= dx;
				y += flag;
			}
		}
	}
	else {
		if (dy < 0) {
			i = x1; x1 = x2; x2 = i;
			i = y1; y1 = y2; y2 = i;
			dx = x2 - x1;
			dy = y2 - y1;
		}

		if (dx < 0) flag = -1;
		else flag = 1;
		dx = abs(dx);
		mid = dy >> 1;
		et = 0;
		x = x1;
		y = y1;

		for (i = 0; i < dy; i++) {
			video_put_pixel(x, y);
			y++;
			et += dx;
			if (et > mid) {
				et -= dy;
				x += flag;
			}
		}
	}
}

void video_circle(int sx, int sy, int r)
{
	int x, y, d;
	x = 0; y = r; d = 1 - r;
	while(x < y) {
		video_put_pixel(sx + x, sy + y);
		video_put_pixel(sx + y, sy + x);
		video_put_pixel(sx - y, sy + x);
		video_put_pixel(sx - x, sy + y);
		video_put_pixel(sx - x, sy + y);
		video_put_pixel(sx - x, sy - y);
		video_put_pixel(sx - y, sy - x);
		video_put_pixel(sx + y, sy - x);
		video_put_pixel(sx + x, sy - y);

		if(d < 0) d += 2 * x + 3;
		else {
			d += 2 * (x - y) + 5;
			y--;
		}
		x++;
	}
}

void video_rectangle(int x1, int y1, int x2, int y2)
{
	video_line(x1, y1, x2, y1);
	video_line(x2, y2, x2, y1);
	video_line(x1, y2, x2, y2);
	video_line(x1, y2, x1, y1); 
}

void video_bar(int x1, int y1, int x2, int y2)
{
	SDL_Rect ds;
	int t;
	if(x1 > x2) {
		t = x1;
		x1 = x2;
		x2 = t;
	}
	if(y1 > y2) {
		t = y1;
		y1 = y2;
		y2 = t;
	}
	ds.x = x1;
	ds.y = y1;
	ds.w = x2 - x1 + 1;
	ds.h = y2 - y1 + 1;
	
	if(draw_lock) return;
	SDL_FillRect(screen, &ds, fore_color);
}

static int poly_status = 0;
static int poly_x = 0;
static int poly_y = 0;

void video_poly_start()
{
	poly_status = 1;
}

void video_poly_point(int x, int y)
{
	switch(poly_status) {
		case 2:
			video_line(x, y, poly_x, poly_y);
			poly_x = x;
			poly_y = y;
			break;
		case 1:
			poly_x = x;
			poly_y = y;
			poly_status = 2;
			break;
	}
}

void video_poly_end() {
	poly_status = 0;
}


Image video_loadimg(char *filename)
{
	char namebuf[1024];
	Image a, b;
	namebuf[0] = 0;
	strcat(namebuf, respath_get());
	strcat(namebuf, filename);
	
	if((a = IMG_Load(namebuf)) == NULL) return NULL;
	SDL_SetColorKey(a, SDL_SRCCOLORKEY, 0);
	b = a;
	a = SDL_DisplayFormat(a);
	SDL_FreeSurface(b);
	return a;
}

Image video_loadimg_x(char *filename, Uint8 alpha)
{
	char namebuf[1024];
	Image a, b;
	namebuf[0] = 0;
	strcat(namebuf, respath_get());
	strcat(namebuf, filename);

	if((a = IMG_Load(namebuf)) == NULL) return NULL;
	SDL_SetColorKey(a, SDL_SRCCOLORKEY, 0);
	SDL_SetAlpha(a, SDL_SRCALPHA, alpha);
	b = a;
	a = SDL_DisplayFormat(a);
	SDL_FreeSurface(b);
	return a;
}

void video_set_alpha(Image a, Uint8 alpha)
{
	SDL_SetAlpha(a, SDL_SRCALPHA, alpha);
}

void video_drawimg(Image img, int x, int y)
{	//显示图片到屏幕
	SDL_Rect dest;
	if(draw_lock) return;
	dest.x = x;
	dest.y = y;
	SDL_BlitSurface(img, NULL, screen, &dest);
}


void video_drawimg_x(Image img, int sx, int sy,
		     int w, int h, int x, int y)
{
//		图片	截取开始的x,y	截取的宽与高,	作图的xy
	SDL_Rect dd;
	SDL_Rect ds;
	if(draw_lock) return;
	ds.x = sx;
	ds.y = sy;
	ds.w = w;
	ds.h = h;
	dd.x = x;
	dd.y = y;
	SDL_BlitSurface(img, &ds, screen, &dd);
}

void video_destory_img(Image a)
{
	SDL_FreeSurface(a);
}


void video_end_rect(int x1, int y1, int x2, int y2)
{
	
	if (SDL_MUSTLOCK(screen))
		SDL_UnlockSurface(screen);
	
	SDL_UpdateRect(screen, x1, y1, x2 - x1, y2 - y1);
	draw_lock = 1;
}

void video_clear_rect(int x1, int y1, int x2, int y2)
{
	SDL_Rect ds;
	
	ds.x = x1;
	ds.y = y1;
	ds.w = x2 - x1;
	ds.h = y2 - y1;
	
	if(draw_lock) return;
	SDL_FillRect(screen, &ds, 0);
}


void video_rotate_draw(Image img, int sx, int sy, int angle)
{
	if(draw_lock) return;
	
	Image new_img, tmp;
	SDL_Rect dest;
	
	new_img = rotozoomSurface(img, (double) angle, 1, 1);
	
	SDL_SetColorKey(new_img, SDL_SRCCOLORKEY, 0);
	//SDL_SetAlpha(new_img, SDL_SRCALPHA, alpha);
	tmp = new_img;
	new_img = SDL_DisplayFormat(new_img);
	
	dest.x = sx - new_img -> w / 2;
	dest.y = sy - new_img -> h / 2;
	SDL_BlitSurface(new_img, NULL, screen, &dest);
	SDL_FreeSurface(tmp);
	SDL_FreeSurface(new_img);
}

int all_init(char *path_prefix)
{
	respath_init(path_prefix);
	if(video_init()) return -1;			//初始化系统
	if(audio_init()) return -1;
	if(ctrl_init()) return -1;
	if(ttf_init()) return -1;
	return 0;
}
